import datetime

from api import models
from api.extension.auth import TokenAuthentication
from api.extension.mixins import DigCreateModelMixin, DigListModelMixin
from api.serializers.comment import CreateCommentSerializer, ListCommentSerializer
from django_filters import FilterSet, filters
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.viewsets import GenericViewSet


class CommentFilterSet(FilterSet):
    news = filters.NumberFilter(field_name='news', required=True)
    latest_id = filters.DateTimeFilter(field_name='descendant_update_datetime', lookup_expr='lte')

    class Meta:
        model = models.Comment
        fields = ['news', 'latest_id']


"""
1. 按照后代的更新时间，对根评论进行排序
2. 获取根评论的子评论
"""


class CommentView(DigCreateModelMixin, DigListModelMixin, GenericViewSet):
    """ 评论 """
    filter_backends = [DjangoFilterBackend]
    filterset_class = CommentFilterSet

    authentication_classes = [TokenAuthentication]

    queryset = models.Comment.objects.filter(depth=0).order_by('-descendant_update_datetime')
    # serializer_class = CreateCommentSerializer

    def perform_create(self, serializer):
        reply = serializer.validated_data.get('reply')
        user = self.request.user
        if not reply:
            # 自己是根评论 news、content、reply
            instance = serializer.save(user=user)
        else:
            if not reply.root:
                root = reply  # 给根评论回复
            else:
                root = reply.root
            instance = serializer.save(user=user, depth=reply.depth + 1, root=root)
            # 刷新根评论的最近更新时间
            root.descendant_update_datetime = datetime.datetime.now()
            root.save()
        instance.news.comment_count += 1
        instance.news.save()

    def get_serializer_class(self):
        if self.request.method == 'GET':
            return ListCommentSerializer
        return CreateCommentSerializer

    def get_authenticators(self):
        if self.request.method == 'POST':
            return super().get_authenticators()
        return []
